#include "Nand.h"
#pragma  diag_suppress 870
void NAND_Init(void)
{ 
	//初始化NAND FLASH相关IO口
	GPIO_InitTypeDef GPIO_InitStructure; 
	FSMC_NAND_PCCARDTimingInitTypeDef  p;
	FSMC_NANDInitTypeDef FSMC_NANDInitStructure;

	/* Enable GPIOs clock */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF |
					 RCC_AHB1Periph_GPIOG, ENABLE);


	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

	/* Enable FSMC clock */
	RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); 

	/*-- GPIOs Configuration ------------------------------------------------------*/

	/* GPIOD configuration */
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);/*FSMC_D2*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);/*FSMC_D3*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);/*FSMC_NOE*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);/*FSMC_NWE*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC);/*FSMC_NCE2*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);/*FSMC_A16*/ 
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FSMC);/*FSMC_A17*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);/*FSMC_D0*/
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);/*FSMC_D1*/

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | 
							GPIO_Pin_7 | GPIO_Pin_11 |
							GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

	GPIO_Init(GPIOD, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

	GPIO_Init(GPIOG, &GPIO_InitStructure);


	/* GPIOE configuration */
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FSMC);/*FSMC_D4*/
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FSMC);/*FSMC_D5*/
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FSMC);/*FSMC_D6*/
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FSMC);/*FSMC_D7*/

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 |GPIO_Pin_8  | GPIO_Pin_9  | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOE, &GPIO_InitStructure);

	p.FSMC_SetupTime = 0x01;
	p.FSMC_WaitSetupTime = 0x03;
	p.FSMC_HoldSetupTime = 0x01;
	p.FSMC_HiZSetupTime = 0x01; 

	FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND;
	FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Disable;
	FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
	FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Disable;
	FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
	FSMC_NANDInitStructure.FSMC_TCLRSetupTime =0;
	FSMC_NANDInitStructure.FSMC_TARSetupTime = 0;
	FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
	FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;

	FSMC_NANDInit(&FSMC_NANDInitStructure);

	/*!< FSMC NAND Bank Cmd Test */
	FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);

    delay_ms(100);

} 


//读NAND状态
//返回值:NAND状态值
//bit0:0,成功;1,错误(编程/擦除/READ)
//bit6:0,Busy;1,Ready
u8 NAND_ReadStatus(void)
{
    vu8 data=0; 
    *(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_READSTA;//发送读状态命令
	data++;data++;data++;data++;data++;	//加延时,防止-O2优化,导致的错误.
 	data=*(vu8*)NAND_ADDRESS;			//读取状态值
    return data;
}
//等待NAND准备好
//返回值:NSTA_TIMEOUT 等待超时了
//      NSTA_READY    已经准备好
u8 NAND_WaitForReady(void)
{
    u8 status=0;
    vu32 time=0; 
	while(1)						//等待ready
	{
		status=NAND_ReadStatus();	//获取状态值
		if(status&NSTA_READY)break;
		time++;
		if(time>=0X1FFFF)return NSTA_TIMEOUT;//超时
	}  
    return NSTA_READY;//准备好
} 

//擦除一个块
//BlockNum:要擦除的BLOCK编号,范围:0-(block_totalnum-1)
//返回值:0,擦除成功
//    其他,擦除失败
u8 NAND_EraseBlock(u32 BlockNum)
{
	BlockNum<<=7;  	//将块地址转换为页地址
    *(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_ERASE0;
    //发送块地址
    *(vu8*)(NAND_ADDRESS|NAND_ADDR)=(u8)BlockNum;
    *(vu8*)(NAND_ADDRESS|NAND_ADDR)=(u8)(BlockNum>>8);
    *(vu8*)(NAND_ADDRESS|NAND_ADDR)=(u8)(BlockNum>>16);
    *(vu8*)(NAND_ADDRESS|NAND_CMD)=NAND_ERASE1;
	if(NAND_WaitForReady()!=NSTA_READY)return NSTA_ERROR;//失败
    return 0;	//成功   
} 
//全片擦除NAND FLASH
void NAND_EraseChip(void)
{
    u16 i=0;
    for(i=0;i<4096;i++) //循环擦除所有的块
    {
        NAND_EraseBlock(i);
    }
}
fsStatus Nand_FS_Init(char* path)
{
	fsStatus state;
	state = finit (path);
	if (state == fsOK)
	{
		state = fmount (path);
		if (state == fsNoFileSystem) 
		{
			printf (" NandFlash 没有格式化!\r\n");
			NAND_EraseChip();
			state = cmd_format (path); 
			if(state == fsOK)
				printf (" NandFlash 格式化成功!\r\n");
			else
				printf (" NandFlash 格式化失败!\r\n");
		}			
	}
	return state;
}

static char *get_drive (char *src, char *dst, uint32_t dst_sz) {
    uint32_t i, n;

    i = 0;
    n = 0;
    while (!n && src && src[i] && (i < dst_sz)) 
    {
        dst[i] = src[i];
        if (dst[i] == ':') 
        {
            n = i + 1;
        }
        i++;
    }
    if (n == dst_sz) 
    {
        n = 0;
    }
    dst[n] = '\0';

    return (src + n);
}

/*-----------------------------------------------------------------------------
 *  NandFlash文件系统格式化
 *----------------------------------------------------------------------------*/
fsStatus cmd_format (char *par) 
{
    char  drive[4];
    par = get_drive (par, drive, 4);
    if (fformat (drive, par) == fsOK) 
        return fsOK;                //格式化 成功
    else 
        return fsError;             //格式化 失败

}

